home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Utilities / MView / mdraw.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-30  |  34.9 KB  |  996 lines

  1. /*//////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File: mdraw.h
  4. //
  5. // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  6. //
  7. //
  8. //////////////////////////////////////////////////////////////////////////////*/
  9.  
  10. #include "mviewpch.h"
  11.  
  12. const WORD x_rglineBBox[24] = { 0, 1,  0, 2,  0, 4,  7, 6,  7, 5,  7, 3,
  13.                                 1, 3,  1, 5,  2, 3,  2, 6,  4, 5,  4, 6 };
  14.  
  15. D3DTRANSFORMSTATETYPE worldMatHandles[] = { D3DTS_WORLD,
  16.                                             D3DTS_WORLD1,
  17.                                             D3DTS_WORLD2,
  18.                                             D3DTS_WORLD3 };
  19. HRESULT GenerateMesh(SMeshContainer *pmcMesh);
  20.  
  21. HRESULT 
  22. TrivialData::DrawSubset
  23.     (
  24.     LPD3DXBASEMESH pMesh, 
  25.     LPD3DXEFFECT pEffect, 
  26.     SEffectInfo *pEffectInfo, 
  27.     DWORD ipattr, 
  28.     SMeshContainer *pmcMesh, 
  29.     BOOL bSelected, 
  30.     D3DXMATRIX *rgmIndexedMatrices, 
  31.     DWORD cIndexedMatrices
  32.     )
  33. {
  34.     static LPCSTR mWd[8] = { "mWd0", "mWd1", "mWd2", "mWd3",  "mWd4", "mWd5", "mWd6", "mWd7"};
  35.  
  36.     HRESULT hr = S_OK;
  37.     UINT iPass;
  38.     UINT cPasses;
  39.     LPD3DXEFFECT pfx;
  40.     DWORD iae;
  41.     LPDIRECT3DVERTEXBUFFER9 pVertexBuffer;
  42.     LPDIRECT3DINDEXBUFFER9 pIndexBuffer;
  43.     DWORD cBytesPerVertex;
  44.  
  45.     if (pmcMesh->bNPatchMode && m_bHWNPatches)
  46.     {
  47.         float fSegments;
  48.         fSegments = (float)pmcMesh->cTesselateLevel + 1.0f;
  49.         m_pDevice->SetNPatchMode(fSegments);
  50.     }
  51.  
  52.     // Strip support is currently disabled
  53. #if 0
  54.     if (pmcMesh->m_rgpStrips != NULL)
  55.     {
  56.         LPDIRECT3DVERTEXBUFFER9 pVertexBuffer;
  57.         DWORD dwFVF;
  58.         DWORD cBytesPerVertex;
  59.  
  60.         dwFVF = pMesh->GetFVF();
  61.         cBytesPerVertex = D3DXGetFVFVertexSize(dwFVF);
  62.         pMesh->GetVertexBuffer(&pVertexBuffer);
  63.  
  64.         m_pDevice->SetFVF(dwFVF);
  65.         m_pDevice->SetStreamSource(0, pVertexBuffer, 0, cBytesPerVertex);
  66.         m_pDevice->SetIndices(pmcMesh->m_rgpStrips[ipattr]);
  67.  
  68.         if (pmcMesh->m_rgcStripIndices != NULL)
  69.         {
  70.             hr = m_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 
  71.                                          0, 0, pMesh->GetNumVertices(),
  72.                                          0, pmcMesh->m_rgcStripIndices[ipattr] - 2);
  73.             if (FAILED(hr))
  74.                 goto e_Exit;
  75.         }
  76.         else
  77.         {
  78.             DWORD iStripStart;
  79.             DWORD iStrip;
  80.  
  81.             iStripStart = 0;
  82.             for (iStrip = 0; iStrip < pmcMesh->m_rgcStrips[ipattr]; iStrip++)
  83.             {
  84.                 hr = m_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 
  85.                                              0, 0, pMesh->GetNumVertices(),
  86.                                              iStripStart, m_pmcSelectedMesh->m_rgrgcStripCounts[ipattr][iStrip]);
  87.                 if (FAILED(hr))
  88.                     goto e_Exit;
  89.  
  90.                 iStripStart += 2 + m_pmcSelectedMesh->m_rgrgcStripCounts[ipattr][iStrip];
  91.             }
  92.         }
  93.  
  94.         pVertexBuffer->Release();
  95.     }
  96.     else //if ((pEffect != NULL))// && !pEffect->BDefaultEffect())
  97. #endif
  98.     {
  99.         GXASSERT(pEffect != NULL);
  100.  
  101.         D3DXMATRIX matView, matProj, matWorld, matTot;
  102.         
  103.         m_pDevice->GetTransform(D3DTS_VIEW,&matView);
  104.         m_pDevice->GetTransform(D3DTS_PROJECTION,&matProj);
  105.  
  106.         hr = SetEffectMatrices(pEffect, pEffectInfo, &matProj, &matView, rgmIndexedMatrices, cIndexedMatrices,  NULL, 0, m_pdeHead->fCurTime);
  107.         if (FAILED(hr))
  108.             goto e_Exit;
  109.  
  110.         pEffect->Begin(&cPasses, 0);
  111.  
  112.         for (iPass = 0; iPass < cPasses; iPass++)
  113.         {
  114.  
  115.             pEffect->BeginPass(iPass);
  116.  
  117.             hr = pMesh->DrawSubset(ipattr);
  118.             if (FAILED(hr))
  119.                 goto e_Exit;
  120.  
  121.             pEffect->EndPass();
  122.         }
  123.         pEffect->End();
  124.     }
  125.  
  126.     if (pmcMesh->bNPatchMode && m_bHWNPatches)
  127.     {
  128.         m_pDevice->SetNPatchMode(0);
  129.     }
  130.  
  131.     if ((bSelected && m_bFaceSelectionMode && (m_dwFaceSelected != UNUSED32)) 
  132.         || (bSelected && m_bVertexSelectionMode && (m_dwVertexSelected != UNUSED32)) 
  133.         || m_bEdgeMode || m_bNPatchEdgeMode || m_bStripMode || m_bCreaseMode || m_bNormalsMode || m_bAdjacencyMode || m_dwTexCoordsShown)
  134.     {
  135.         DWORD dwFillMode;
  136.  
  137.         D3DXMATRIX mTrans(
  138.             1.f, 0.f, 0.f, 0.f,
  139.             0.f, 1.f, 0.f, 0.f,
  140.             0.f, 0.f, 1.f, 0.f,
  141.             0.f, 0.f, 0.f, 1.f);
  142.         D3DXMATRIX mTransOrig;
  143.  
  144.         m_pDevice->GetRenderState( D3DRS_FILLMODE, &dwFillMode );
  145.         m_pDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
  146.  
  147.  
  148.         hr = m_pDevice->GetTransform(D3DTS_VIEW, &mTrans);
  149.         if(FAILED(hr))
  150.                 return hr;
  151.  
  152.         mTransOrig = mTrans;
  153.  
  154.         mTrans._43 -= (m_pdeSelected == NULL ? m_pdeHead : m_pdeSelected)->fRadius / 800.0f;
  155.  
  156.         hr = m_pDevice->SetTransform(D3DTS_VIEW, &mTrans);
  157.         if(FAILED(hr))
  158.             goto e_Exit;
  159.  
  160.         if (m_bAdjacencyMode && ((pmcMesh->pSkinInfo == NULL) || (pmcMesh->m_Method != SOFTWARE)) && (!pmcMesh->bNPatchMode))
  161.         {
  162.             hr = pmcMesh->m_aoAdjacency.Draw(m_pDevice, ipattr, m_pfxSkinnedAdjacency, m_pfxFaceSelect, 0xff004f4f, rgmIndexedMatrices, cIndexedMatrices);
  163.             if(FAILED(hr))
  164.                 return hr;
  165.  
  166.             // offset view some more in case of strip mode.  so strip mode will show up on top
  167.             mTrans._43 -= (m_pdeSelected == NULL ? m_pdeHead : m_pdeSelected)->fRadius / 800.0f;
  168.  
  169.             hr = m_pDevice->SetTransform(D3DTS_VIEW, &mTrans);
  170.             if(FAILED(hr))
  171.                     return hr;
  172.         }
  173.  
  174.         if (m_bStripMode && ((pmcMesh->pSkinInfo == NULL) || (pmcMesh->m_Method != SOFTWARE)) && (!pmcMesh->bNPatchMode))
  175.         {
  176.             hr = pmcMesh->m_soStrips.Draw(m_pDevice, ipattr, m_pfxSkinnedAdjacency, m_pfxFaceSelect, 0xff40a0ff, rgmIndexedMatrices, cIndexedMatrices);
  177.             if(FAILED(hr))
  178.                 return hr;
  179.         }
  180.  
  181.         // do edge mode first, so selected face and other options are above it
  182.         if (m_bEdgeMode)
  183.         {
  184.             D3DXCOLOR color(0.0f, 0.0f, 0.0f, 1.0f);
  185.  
  186.             if (pmcMesh->bNPatchMode && m_bHWNPatches)
  187.             {
  188.                 float fSegments;
  189.                 fSegments = (float)pmcMesh->cTesselateLevel + 1.0f;
  190.                 m_pDevice->SetNPatchMode(fSegments);
  191.             }
  192.  
  193.             m_pfxFaceSelect->SetVector("vClr", (D3DXVECTOR4*)&color);
  194.             m_pfxFaceSelect->Begin(&cPasses, 0);
  195.  
  196.             for (iPass = 0; iPass < cPasses; iPass++)
  197.             {
  198.                 m_pfxFaceSelect->BeginPass(iPass);
  199.  
  200.                 hr = pMesh->DrawSubset( ipattr );
  201.                 if(FAILED(hr))
  202.                     goto e_Exit;
  203.  
  204.                 m_pfxFaceSelect->EndPass();
  205.             }
  206.             m_pfxFaceSelect->End();
  207.  
  208.             if (pmcMesh->bNPatchMode && m_bHWNPatches)
  209.             {
  210.                 m_pDevice->SetNPatchMode(0);
  211.             }
  212.  
  213.             // if edge mode, move the view transform again, so that the later options will be on top
  214.             mTrans._43 -= (m_pdeSelected == NULL ? m_pdeHead : m_pdeSelected)->fRadius / 800.0f;
  215.  
  216.             hr = m_pDevice->SetTransform(D3DTS_VIEW, &mTrans);
  217.             if(FAILED(hr))
  218.                 goto e_Exit;
  219.         }
  220.  
  221.         // do npatch edge mode next, so selected face and other options are above it
  222.         if (m_bNPatchEdgeMode && pmcMesh->bNPatchMode)
  223.         {
  224.             D3DXCOLOR color(1.0f, 0.0f, 1.0f, 1.0f);
  225.  
  226.             m_pfxFaceSelect->SetVector("vClr", (D3DXVECTOR4*)&color);
  227.             m_pfxFaceSelect->Begin(&cPasses, 0);
  228.  
  229.             for (iPass = 0; iPass < cPasses; iPass++)
  230.             {
  231.                 m_pfxFaceSelect->BeginPass(iPass);
  232.  
  233.                 hr = pmcMesh->m_npoNPatchOutline.Draw(pmcMesh->pSWTesselatedMesh, ipattr);
  234.                 if(FAILED(hr))
  235.                     goto e_Exit;
  236.  
  237.                 m_pfxFaceSelect->EndPass();
  238.             }
  239.             m_pfxFaceSelect->End();
  240.  
  241.             // if edge mode, move the view transform again, so that the later options will be on top
  242.             mTrans._43 -= (m_pdeSelected == NULL ? m_pdeHead : m_pdeSelected)->fRadius / 800.0f;
  243.  
  244.             hr = m_pDevice->SetTransform(D3DTS_VIEW, &mTrans);
  245.             if(FAILED(hr))
  246.                 goto e_Exit;
  247.         }
  248.  
  249.         if (bSelected && (m_dwFaceSelectedAttr == ipattr))
  250.         {
  251.             LPD3DXBASEMESH pMeshCur;
  252.             
  253.             if (pmcMesh->bNPatchMode)
  254.                 pMeshCur = pmcMesh->pMeshToTesselate;
  255.             else // skinned, pm, etc
  256.                 pMeshCur = pmcMesh->ptmDrawMesh;
  257.  
  258.             if (m_bFaceSelectionMode && (m_dwFaceSelected != UNUSED32))
  259.             {
  260.                 D3DXCOLOR color(1.0f, 1.0f, 0.0f, 1.0f);
  261.  
  262.                 if (!pmcMesh->bNPatchMode)
  263.                 {
  264.                     DWORD dwFVF;
  265.                     DWORD cBytesPerVertex;
  266.                     PBYTE pbVertices;
  267.                     PBYTE pbCur;
  268.                     PBYTE pbVerticesSrc;
  269.                     DWORD *pwFace;
  270.         
  271.                     //pMeshCur = pmcMesh->m_pSkinnedMesh != NULL ? pmcMesh->m_pSkinnedMesh : pMesh;
  272.  
  273.                     dwFVF = pMeshCur->GetFVF();
  274.                     cBytesPerVertex = D3DXGetFVFVertexSize(dwFVF);
  275.                     pMeshCur->GetVertexBuffer(&pVertexBuffer);
  276.                     pMeshCur->GetIndexBuffer(&pIndexBuffer);
  277.  
  278.                     pbVertices = (PBYTE)_alloca(cBytesPerVertex * 3);
  279.  
  280.                     m_pfxFaceSelect->SetVector("vClr", (D3DXVECTOR4*)&color);
  281.                     m_pfxFaceSelect->Begin(&cPasses, 0);
  282.  
  283.                     for (iPass = 0; iPass < cPasses; iPass++)
  284.                     {
  285.                         m_pfxFaceSelect->BeginPass(iPass);
  286.  
  287.                         m_pDevice->SetFVF(dwFVF);
  288.  
  289.                         if (pMeshCur->GetOptions() & D3DXMESH_32BIT)
  290.                         {
  291.                             pMeshCur->LockVertexBuffer(0, (PVOID*)&pbVerticesSrc);
  292.                             pMeshCur->LockIndexBuffer(0, (PVOID*)&pwFace);
  293.                             pwFace += m_dwFaceSelected * 3;
  294.  
  295.                             pbCur = pbVertices;
  296.                             memcpy(pbCur, pbVerticesSrc + pwFace[0] * cBytesPerVertex, cBytesPerVertex);
  297.                             pbCur += cBytesPerVertex;
  298.                             memcpy(pbCur, pbVerticesSrc + pwFace[1] * cBytesPerVertex, cBytesPerVertex);
  299.                             pbCur += cBytesPerVertex;
  300.                             memcpy(pbCur, pbVerticesSrc + pwFace[2] * cBytesPerVertex, cBytesPerVertex);
  301.                             pbCur += cBytesPerVertex;
  302.  
  303.                             pMeshCur->UnlockVertexBuffer();
  304.                             pMeshCur->UnlockIndexBuffer();
  305.  
  306.                             hr = m_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 1, pbVertices, cBytesPerVertex);
  307.                             if (FAILED(hr))
  308.                                 goto e_Exit;                
  309.                         }
  310.                         else
  311.                         {
  312.                             m_pDevice->SetStreamSource(0, pVertexBuffer, 0, cBytesPerVertex);
  313.                             m_pDevice->SetIndices(pIndexBuffer);
  314.  
  315.                             hr = m_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
  316.                                                          0, 0, pMeshCur->GetNumVertices(),
  317.                                                          m_dwFaceSelected * 3, 1);
  318.                             if(FAILED(hr))
  319.                                 goto e_Exit;
  320.                         }
  321.  
  322.                         m_pfxFaceSelect->EndPass();
  323.                     }
  324.  
  325.                     m_pfxFaceSelect->End();
  326.  
  327.                     pVertexBuffer->Release();
  328.                     pIndexBuffer->Release();
  329.                 }
  330.                 else // show npatch selected face
  331.                 {
  332.                     m_pfxFaceSelect->SetVector("vClr", (D3DXVECTOR4*)&color);
  333.                     m_pfxFaceSelect->Begin(&cPasses, 0);
  334.  
  335.                     for (iPass = 0; iPass < cPasses; iPass++)
  336.                     {
  337.                         m_pfxFaceSelect->BeginPass(iPass);
  338.  
  339.                         hr = pmcMesh->m_npoNPatchOutline.DrawFace(pmcMesh->pSWTesselatedMesh, m_dwFaceSelected, ipattr);
  340.                         if(FAILED(hr))
  341.                             goto e_Exit;
  342.  
  343.                         m_pfxFaceSelect->EndPass();
  344.                     }
  345.                     m_pfxFaceSelect->End();
  346.                 }
  347.             }
  348.  
  349.             if (m_bVertexSelectionMode && (m_dwVertexSelected != UNUSED32)) 
  350.             {
  351.                 DWORD dwFVF;
  352.                 DWORD cBytesPerVertex;
  353.                 LPDIRECT3DVERTEXBUFFER9 pVertexBuffer;
  354.                 LPDIRECT3DINDEXBUFFER9 pIndexBuffer;
  355.                 //pMeshCur = pmcMesh->m_pSkinnedMesh != NULL ? pmcMesh->m_pSkinnedMesh : pMesh;
  356.  
  357.                 dwFVF = pMeshCur->GetFVF();
  358.                 cBytesPerVertex = D3DXGetFVFVertexSize(dwFVF);
  359.                 pMeshCur->GetVertexBuffer(&pVertexBuffer);
  360.  
  361.                 GXASSERT(m_dwVertexSelected < pMeshCur->GetNumVertices());
  362.  
  363.                 m_pfxVertSelect->SetVector("vcol", &D3DXVECTOR4(1.0, 0.0, 0.0f, 1.0f));
  364.                 m_pfxVertSelect->Begin(&cPasses, 0);
  365.  
  366.                 for (iPass = 0; iPass < cPasses; iPass++)
  367.                 {
  368.                     m_pfxVertSelect->BeginPass(iPass);
  369.  
  370.                     m_pDevice->SetFVF(dwFVF);
  371.                     m_pDevice->SetStreamSource(0, pVertexBuffer, 0, cBytesPerVertex);
  372.                     m_pDevice->DrawPrimitive(D3DPT_POINTLIST, m_dwVertexSelected, 1);
  373.                  
  374.                     m_pfxVertSelect->EndPass();
  375.                 }
  376.  
  377.                 m_pfxVertSelect->End();
  378.                 pVertexBuffer->Release();
  379.  
  380.                 // view all normals
  381.                 if (m_bNormalsMode && ((pmcMesh->pSkinInfo == NULL) || (pmcMesh->m_Method != SOFTWARE)))
  382.                 {
  383.                     hr = pmcMesh->m_snNormals.Draw(ipattr, m_dwVertexSelected, m_pfxShowNormals, m_pfxFaceSelect, 0xffffff00, rgmIndexedMatrices, cIndexedMatrices);
  384.                     if(FAILED(hr))
  385.                         return hr;
  386.                 }
  387.  
  388.                 if ((m_dwTexCoordsShown != 0) && ((pmcMesh->pSkinInfo == NULL) || (pmcMesh->m_Method != SOFTWARE)))
  389.                 {
  390.                     for (DWORD iTexCoord = 0; iTexCoord < x_cpsnTexCoords; iTexCoord++)
  391.                     {
  392.                         if (m_dwTexCoordsShown & (1<<iTexCoord))
  393.                         {
  394.                             hr = pmcMesh->m_rgpsnTexCoords[iTexCoord]->Draw(ipattr, m_dwVertexSelected, m_pfxShowNormals, m_pfxFaceSelect, 0xffffff00, rgmIndexedMatrices, cIndexedMatrices);
  395.                             if(FAILED(hr))
  396.                                 return hr;
  397.                         }
  398.                     }
  399.                 }
  400.             }
  401.         }
  402.  
  403.         // UNDONE UNDONE - Crease mode does not work if the mesh is split
  404.         if (m_bCreaseMode && (!pmcMesh->bNPatchMode))
  405.         {
  406.             D3DXCOLOR color(1.0f, 2.0f/3.0f, 0.0f, 1.0f);
  407.  
  408.             m_pfxFaceSelect->SetVector("vClr", (D3DXVECTOR4*)&color);
  409.             m_pfxFaceSelect->Begin(&cPasses, 0);
  410.  
  411.             for (iPass = 0; iPass < cPasses; iPass++)
  412.             {
  413.                 m_pfxFaceSelect->BeginPass(iPass);
  414.  
  415.                 hr = pmcMesh->m_eoEdges.Draw(pMesh, ipattr);
  416.                 if(FAILED(hr))
  417.                     return hr;
  418.  
  419.                 m_pfxFaceSelect->EndPass();
  420.             }
  421.  
  422.             m_pfxFaceSelect->End();
  423.         }
  424.  
  425.         // view all normals and/or texture coords
  426.         if (!m_bVertexSelectionMode )
  427.         {
  428.             if (m_bNormalsMode && ((pmcMesh->pSkinInfo == NULL) || (pmcMesh->m_Method != SOFTWARE)))
  429.             {
  430.                 hr = pmcMesh->m_snNormals.Draw(ipattr, UNUSED32, m_pfxShowNormals, m_pfxFaceSelect, 0xffffff00, rgmIndexedMatrices, cIndexedMatrices);
  431.                 if(FAILED(hr))
  432.                     return hr;
  433.             }
  434.  
  435.             if ((m_dwTexCoordsShown != 0) && ((pmcMesh->pSkinInfo == NULL) || (pmcMesh->m_Method != SOFTWARE)))
  436.             {
  437.                 for (DWORD iTexCoord = 0; iTexCoord < x_cpsnTexCoords; iTexCoord++)
  438.                 {
  439.                     if (m_dwTexCoordsShown & (1<<iTexCoord))
  440.                     {
  441.                         hr = pmcMesh->m_rgpsnTexCoords[iTexCoord]->Draw(ipattr, UNUSED32, m_pfxShowNormals, m_pfxFaceSelect, 0xffffff00, rgmIndexedMatrices, cIndexedMatrices);
  442.                         if(FAILED(hr))
  443.                             return hr;
  444.                     }
  445.                 }
  446.             }
  447.         }
  448.  
  449.         m_pDevice->SetRenderState( D3DRS_FILLMODE, dwFillMode );
  450.  
  451.         // restore the view transformation
  452.         hr = m_pDevice->SetTransform(D3DTS_VIEW, &mTransOrig);
  453.         if(FAILED(hr))
  454.             goto e_Exit;
  455.     
  456.     }
  457.  
  458.     if (m_bShowMeshSelectionMode && bSelected && (ipattr == 0))
  459.     {
  460.         D3DXVECTOR3 rgvPoints[8];
  461.         D3DXCOLOR color(1.0f, 1.0f, 0.0f, 1.0f);
  462.         DWORD dwIndexedVertexBlend, dwVertexBlend;
  463.  
  464.         rgvPoints[0] = pmcMesh->m_vBoundingBoxMin;
  465.         rgvPoints[1] = D3DXVECTOR3(pmcMesh->m_vBoundingBoxMin.x, pmcMesh->m_vBoundingBoxMin.y, pmcMesh->m_vBoundingBoxMax.z);
  466.         rgvPoints[2] = D3DXVECTOR3(pmcMesh->m_vBoundingBoxMin.x, pmcMesh->m_vBoundingBoxMax.y, pmcMesh->m_vBoundingBoxMin.z);
  467.         rgvPoints[3] = D3DXVECTOR3(pmcMesh->m_vBoundingBoxMin.x, pmcMesh->m_vBoundingBoxMax.y, pmcMesh->m_vBoundingBoxMax.z);
  468.         rgvPoints[4] = D3DXVECTOR3(pmcMesh->m_vBoundingBoxMax.x, pmcMesh->m_vBoundingBoxMin.y, pmcMesh->m_vBoundingBoxMin.z);
  469.         rgvPoints[5] = D3DXVECTOR3(pmcMesh->m_vBoundingBoxMax.x, pmcMesh->m_vBoundingBoxMin.y, pmcMesh->m_vBoundingBoxMax.z);
  470.         rgvPoints[6] = D3DXVECTOR3(pmcMesh->m_vBoundingBoxMax.x, pmcMesh->m_vBoundingBoxMax.y, pmcMesh->m_vBoundingBoxMin.z);
  471.         rgvPoints[7] = pmcMesh->m_vBoundingBoxMax;
  472.  
  473.         m_pDevice->GetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, &dwIndexedVertexBlend);
  474.         m_pDevice->GetRenderState(D3DRS_VERTEXBLEND, &dwVertexBlend);
  475.         m_pDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
  476.         m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  477.  
  478.         m_pfxFaceSelect->SetVector("vClr", (D3DXVECTOR4*)&color);
  479.         m_pfxFaceSelect->Begin(&cPasses, 0);
  480.  
  481.         for (iPass = 0; iPass < cPasses; iPass++)
  482.         {
  483.             m_pfxFaceSelect->BeginPass(iPass);
  484.  
  485.             m_pDevice->SetFVF(D3DFVF_XYZ);
  486.             m_pDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, 8, 12, (void*)x_rglineBBox, D3DFMT_INDEX16, rgvPoints, 12);
  487.  
  488.             m_pfxFaceSelect->EndPass();
  489.         }
  490.         m_pfxFaceSelect->End();
  491.  
  492.         m_pDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, dwIndexedVertexBlend);
  493.         m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, dwVertexBlend);
  494.     }
  495.  
  496. e_Exit:
  497.     return hr;
  498. }
  499.  
  500. HRESULT
  501. TrivialData::DrawMeshContainer
  502.     (
  503.     SMeshContainer *pmcMesh,
  504.     D3DXMATRIX *pmatWorld
  505.     )
  506. {
  507.     UINT ipattr;
  508.     DWORD cAttr;
  509.     HRESULT hr;
  510.     LPD3DXBONECOMBINATION pBoneComb;
  511.     DWORD AttribIdPrev;
  512.     UINT iPass;
  513.     UINT cPasses;
  514.     
  515.     if (pmcMesh->pSkinInfo)
  516.     {
  517.         D3DCAPS9    caps;
  518.  
  519.         m_pDevice->GetDeviceCaps(&caps);
  520.  
  521.         if ((m_method != pmcMesh->m_Method) && !pmcMesh->m_bOverrideMethod)
  522.         {
  523.             pmcMesh->m_Method = m_method;
  524.             GenerateMesh(pmcMesh);
  525.  
  526.             pmcMesh->UpdateViews(m_pdeHead);
  527.         }
  528.  
  529.         if (pmcMesh->m_Method == D3DNONINDEXED)
  530.         {
  531.             AttribIdPrev = UNUSED32; 
  532.             pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer());
  533.  
  534.             // Draw using default vtx processing of the device (typically HW)
  535.             for (ipattr = 0; ipattr < pmcMesh->m_cAttributeGroups; ipattr++)
  536.             {
  537.                 DWORD numBlend = 0;
  538.                 for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i)
  539.                 {
  540.                     if (pBoneComb[ipattr].BoneId[i] != UINT_MAX)
  541.                     {
  542.                         numBlend = i;
  543.                     }
  544.                 }
  545.  
  546.                 if (m_Caps.MaxVertexBlendMatrices >= numBlend + 1)
  547.                 {
  548.                     for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i)
  549.                     {
  550.                         DWORD matid = pBoneComb[ipattr].BoneId[i];
  551.                         if (matid != UINT_MAX)
  552.                         {
  553.                             D3DXMatrixMultiply(&m_mMatrices[i], &pmcMesh->pBoneOffsetMatrices[matid], pmcMesh->m_pBoneMatrix[matid]);
  554.  
  555.                             m_pDevice->SetTransform(D3DTS_WORLDMATRIX(i), &m_mMatrices[i]);
  556.                         }
  557.                     }
  558.  
  559.                     m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, numBlend);
  560.  
  561.                     hr = DrawSubset(pmcMesh->ptmDrawMesh, pmcMesh->m_rgpfxAttributes[pBoneComb[ipattr].AttribId], &pmcMesh->m_rgEffectInfo[pBoneComb[ipattr].AttribId], ipattr, pmcMesh, pmcMesh == m_pmcSelectedMesh, m_mMatrices, pmcMesh->m_maxFaceInfl);
  562.                     if(FAILED(hr))
  563.                         return hr;
  564.                 }
  565.  
  566.             }
  567.  
  568.             // If necessary, draw parts that HW could not handle using SW
  569.             if (pmcMesh->iAttrSplit < pmcMesh->m_cAttributeGroups)
  570.             {
  571.                 AttribIdPrev = UNUSED32; 
  572.                 if (!m_bSoftwareVP)
  573.                 {
  574.                     m_pDevice->SetSoftwareVertexProcessing(TRUE);
  575.                 }
  576.  
  577.                 for (ipattr = pmcMesh->iAttrSplit; ipattr < pmcMesh->m_cAttributeGroups; ipattr++)
  578.                 {
  579.                     DWORD numBlend = 0;
  580.                     for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i)
  581.                     {
  582.                         if (pBoneComb[ipattr].BoneId[i] != UINT_MAX)
  583.                         {
  584.                             numBlend = i;
  585.                         }
  586.                     }
  587.  
  588.                     if (m_Caps.MaxVertexBlendMatrices < numBlend + 1)
  589.                     {
  590.                         for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i)
  591.                         {
  592.                             DWORD matid = pBoneComb[ipattr].BoneId[i];
  593.                             if (matid != UINT_MAX)
  594.                             {
  595.                                 D3DXMatrixMultiply(&m_mMatrices[i], &pmcMesh->pBoneOffsetMatrices[matid], pmcMesh->m_pBoneMatrix[matid]);
  596.  
  597.                                 m_pDevice->SetTransform(D3DTS_WORLDMATRIX(i), &m_mMatrices[i]);
  598.                             }
  599.                         }
  600.  
  601.                         m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, numBlend);
  602.  
  603.                         hr = DrawSubset(pmcMesh->ptmDrawMesh, pmcMesh->m_rgpfxAttributes[pBoneComb[ipattr].AttribId], &pmcMesh->m_rgEffectInfo[pBoneComb[ipattr].AttribId], ipattr, pmcMesh, pmcMesh == m_pmcSelectedMesh, m_mMatrices, pmcMesh->m_maxFaceInfl);
  604.                         if(FAILED(hr))
  605.                             return hr;
  606.                     }
  607.                 }
  608.                 if (!m_bSoftwareVP)
  609.                     m_pDevice->SetSoftwareVertexProcessing(FALSE);
  610.             }
  611.             m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  612.  
  613.         }
  614.         else if (pmcMesh->m_Method == D3DINDEXED)
  615.         {
  616.            if ((caps.MaxVertexBlendMatrixIndex / 2 /*div2 because we need the inverse transpose for the normals*/) < pmcMesh->pSkinInfo->GetNumBones())
  617.             {
  618.                 // UNDONE UNDONE - need to know when vertex shaders are doing the skinning
  619.                 if ((pmcMesh->m_iPaletteSize == x_iDefaultSkinningPaletteSize) && (!m_bSoftwareVP))
  620.                 {
  621.                     m_pDevice->SetSoftwareVertexProcessing(TRUE);
  622.                 }
  623.             }
  624.  
  625.             m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, pmcMesh->m_maxFaceInfl - 1);
  626.             if (pmcMesh->m_maxFaceInfl - 1)
  627.                 m_pDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);
  628.             pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer());
  629.             for (ipattr = 0; ipattr < pmcMesh->m_cAttributeGroups; ipattr++)
  630.             {
  631.                 for (DWORD i = 0; i < pmcMesh->m_iPaletteSize/*paletteSize*/; ++i)
  632.                 {
  633.                     DWORD matid = pBoneComb[ipattr].BoneId[i];
  634.                     if (matid != UINT_MAX)
  635.                     {
  636.                         D3DXMatrixMultiply(&m_mMatrices[i], &pmcMesh->pBoneOffsetMatrices[matid], pmcMesh->m_pBoneMatrix[matid]);
  637.  
  638.                         m_pDevice->SetTransform(D3DTS_WORLDMATRIX(i), &m_mMatrices[i]);
  639.                     }
  640.                 }
  641.                 
  642.                 hr = DrawSubset(pmcMesh->ptmDrawMesh, pmcMesh->m_rgpfxAttributes[pBoneComb[ipattr].AttribId], &pmcMesh->m_rgEffectInfo[pBoneComb[ipattr].AttribId], ipattr, pmcMesh, pmcMesh == m_pmcSelectedMesh, m_mMatrices, pmcMesh->m_iPaletteSize);
  643.                 if(FAILED(hr))
  644.                     return hr;
  645.             }
  646.             m_pDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
  647.             m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  648.  
  649.             if (caps.MaxVertexBlendMatrixIndex < pmcMesh->pSkinInfo->GetNumBones())
  650.             {
  651.                 if ((pmcMesh->m_iPaletteSize == x_iDefaultSkinningPaletteSize) && !m_bSoftwareVP)
  652.                 {
  653.                     m_pDevice->SetSoftwareVertexProcessing(FALSE);
  654.                 }
  655.             }
  656.         }
  657.         else if (pmcMesh->m_Method == SOFTWARE)
  658.         {
  659.             D3DXMATRIX  Identity;
  660.             PBYTE       pbVerticesSrc;
  661.             PBYTE       pbVerticesDest;
  662.  
  663.             DWORD       cBones  = pmcMesh->pSkinInfo->GetNumBones();
  664.  
  665.             // set up bone transforms
  666.  
  667.             D3DXMATRIX* rgBoneMatrices  = NULL;
  668.             
  669.             rgBoneMatrices  = new D3DXMATRIX[cBones];
  670.  
  671.             if (rgBoneMatrices == NULL)
  672.             {
  673.                 hr = E_OUTOFMEMORY;
  674.  
  675.                 goto e_ExitSOFTWARE;
  676.             }
  677.  
  678.             {
  679.             for (DWORD iBone = 0; iBone < cBones; ++iBone)
  680.             {
  681.                 D3DXMatrixMultiply
  682.                 (
  683.                     &rgBoneMatrices[iBone],                 // output
  684.                     &pmcMesh->pBoneOffsetMatrices[iBone], 
  685.                     pmcMesh->m_pBoneMatrix[iBone]
  686.                 );
  687.             }
  688.             }
  689.  
  690.             // set world transform
  691.             D3DXMatrixIdentity(&Identity);
  692.  
  693.             hr = m_pDevice->SetTransform(D3DTS_WORLD, &Identity);
  694.  
  695.             if (FAILED(hr))
  696.                 goto e_ExitSOFTWARE;
  697.  
  698.             pmcMesh->m_pOrigMesh->LockVertexBuffer(D3DLOCK_READONLY, (PVOID*)&pbVerticesSrc);
  699.             pmcMesh->pMesh->LockVertexBuffer(D3DLOCK_DISCARD, (PVOID*)&pbVerticesDest);
  700.  
  701.             // generate skinned mesh
  702.             hr = pmcMesh->pSkinInfo->UpdateSkinnedMesh(rgBoneMatrices, NULL, pbVerticesSrc, pbVerticesDest);
  703.             pmcMesh->m_pOrigMesh->UnlockVertexBuffer();
  704.             pmcMesh->pMesh->UnlockVertexBuffer();
  705.  
  706.             if (FAILED(hr))
  707.                 goto e_ExitSOFTWARE;
  708.  
  709.             for (ipattr = 0; ipattr < pmcMesh->m_cAttributeGroups; ipattr++)
  710.             {
  711.                 hr = DrawSubset(pmcMesh->ptmDrawMesh, pmcMesh->m_rgpfxAttributes[ipattr], &pmcMesh->m_rgEffectInfo[ipattr], ipattr, pmcMesh, pmcMesh == m_pmcSelectedMesh, m_mMatrices, 1);
  712.                 if (FAILED(hr))
  713.                     goto e_ExitSOFTWARE;
  714.             }
  715.  
  716. e_ExitSOFTWARE:
  717.  
  718.             delete[] rgBoneMatrices;
  719.  
  720.             return hr;
  721.         }
  722.     }
  723.     else
  724.     {
  725.         GXASSERT(pmcMesh->m_cAttributeGroups == pmcMesh->NumMaterials);
  726.  
  727.         m_pDevice->SetTransform(D3DTS_WORLD, pmatWorld);
  728.         m_mMatrices[0] = *pmatWorld;
  729.  
  730.         for (ipattr = 0; ipattr < pmcMesh->m_cAttributeGroups; ipattr++)
  731.         {
  732.             hr = DrawSubset(pmcMesh->ptmDrawMesh, pmcMesh->m_rgpfxAttributes[ipattr], &pmcMesh->m_rgEffectInfo[ipattr], ipattr, pmcMesh, pmcMesh == m_pmcSelectedMesh, m_mMatrices, 1);
  733.             if(FAILED(hr))
  734.                 return hr;
  735.         }
  736.  
  737. #if 0
  738.         D3DXMATRIX matOrig;
  739.         D3DXMATRIX matNew;
  740.  
  741.         m_pDevice->GetTransform(D3DTS_WORLD, &matOrig);
  742.  
  743.         D3DXMatrixAffineTransformation(&matNew, -m_pdeHead->fRadius, NULL, NULL, &m_pdeHead->vCenter);
  744.         D3DXMatrixMultiply(&matNew, &matNew, &matOrig);
  745.  
  746.         m_pDevice->SetTransform(D3DTS_WORLD, &matNew);
  747.  
  748.         m_ShowArcball.Draw(m_pfxFaceSelect, 0xffffff00);
  749.  
  750.         m_pDevice->SetTransform(D3DTS_WORLD, &matOrig);
  751. #endif
  752.  
  753.     }
  754.  
  755.     return S_OK;
  756. }
  757.  
  758. HRESULT
  759. TrivialData::UpdateFrames(SFrame *pframeCur, D3DXMATRIX &matCur)
  760. {
  761.     HRESULT hr = S_OK;
  762.     pframeCur->matCombined = matCur;
  763.     D3DXMatrixMultiply(&pframeCur->matCombined, &pframeCur->matRot, &matCur);
  764.     D3DXMatrixMultiply(&pframeCur->matCombined, &pframeCur->matCombined, &pframeCur->matTrans );
  765.     SFrame *pframeChild = pframeCur->pframeFirstChild;
  766.     while (pframeChild != NULL)
  767.     {
  768.         hr = UpdateFrames(pframeChild, pframeCur->matCombined);
  769.         if (FAILED(hr))
  770.             return hr;
  771.  
  772.         pframeChild = pframeChild->pframeSibling;
  773.     }
  774.     return S_OK;
  775. }
  776.  
  777. HRESULT
  778. TrivialData::DrawFrames(SFrame *pframeCur, UINT &cTriangles, UINT &cVertices)
  779. {
  780.     HRESULT hr = S_OK;
  781.     SMeshContainer *pmcMesh;
  782.     SFrame *pframeChild;
  783.  
  784.     if (pframeCur->pmcMesh != NULL)
  785.     {
  786.         if(FAILED(hr))
  787.             return hr;
  788.     }
  789.  
  790.     pmcMesh = pframeCur->pmcMesh;
  791.     while (pmcMesh != NULL)
  792.     {
  793.         if (pmcMesh->ptmDrawMesh != NULL)
  794.         {
  795.             cTriangles += pmcMesh->ptmDrawMesh->GetNumFaces();
  796.             cVertices += pmcMesh->ptmDrawMesh->GetNumVertices();
  797.  
  798.             hr = DrawMeshContainer(pmcMesh, &pframeCur->matCombined);
  799.             if (FAILED(hr))
  800.                 return hr;
  801.         }
  802.  
  803.         pmcMesh = (SMeshContainer*)pmcMesh->pNextMeshContainer;
  804.     }
  805.  
  806.     pframeChild = pframeCur->pframeFirstChild;
  807.     while (pframeChild != NULL)
  808.     {
  809.         hr = DrawFrames(pframeChild, cTriangles, cVertices);
  810.         if (FAILED(hr))
  811.             return hr;
  812.  
  813.         pframeChild = pframeChild->pframeSibling;
  814.     }
  815.  
  816.     return S_OK;
  817. }
  818.  
  819.  
  820. HRESULT
  821. TrivialData::OnDraw(float fAspect)
  822. {
  823.     UINT cTriangles = 0;
  824.     UINT cVertices = 0;
  825.     UINT cSelectedTriangles = 0;
  826.     UINT cSelectedVertices = 0;
  827.     HRESULT hr;
  828.         SDrawElement *pdeCur;
  829.     D3DXMATRIX matD3D;
  830.     D3DXMATRIX mOut;
  831.     D3DXMATRIX mCur;
  832.     D3DXVECTOR3 vTemp;
  833.     D3DXMATRIX mObject;
  834.     D3DXMATRIX mTrans;
  835.     D3DLIGHT9 light;
  836.     D3DXVECTOR3 vLightDirection;
  837.  
  838.     if (m_pdeHead == NULL)
  839.     {
  840.         if(m_pDevice)
  841.             m_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(120,120,120), 1.0f, 0 );
  842.         return S_OK;
  843.     }
  844.  
  845.     D3DXMatrixTranslation(&mTrans, 0, 0, (m_pdeSelected == NULL ? m_pdeHead : m_pdeSelected)->fRadius * 2.8f);
  846.  
  847.     hr = m_pDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&mTrans);
  848.     if(FAILED(hr))
  849.         return hr;
  850.  
  851.     //m_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(89,135,179), 1.0f, 0 );
  852.     m_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(120,120,120), 1.0f, 0 );
  853.  
  854.     pdeCur = m_pdeHead;
  855.     while (pdeCur != NULL)
  856.     {
  857.         hr = m_pDevice->GetLight(0, &light );
  858.         if (FAILED(hr))
  859.             return E_FAIL;
  860.  
  861.         vLightDirection = D3DXVECTOR3( 0.0f, 0.0f, -1.0f);
  862.  
  863.         D3DXVec3TransformNormal(&vLightDirection, &vLightDirection, &pdeCur->pframeRoot->matRot);
  864.         light.Direction    = vLightDirection;
  865.  
  866.         //hr = m_pDevice->SetLight(0, &light );
  867.         if (FAILED(hr))
  868.             return E_FAIL;
  869.  
  870.         D3DXMatrixIdentity(&mCur);
  871.  
  872.         hr = UpdateFrames(pdeCur->pframeRoot, mCur);
  873.         if (FAILED(hr))
  874.             return hr;
  875.         hr = DrawFrames(pdeCur->pframeRoot, cTriangles, cVertices);
  876.         if (FAILED(hr))
  877.             return hr;
  878.  
  879.         pdeCur = pdeCur->pdeNext;
  880.     }
  881.  
  882.     if (m_pmcSelectedMesh != NULL)
  883.     {
  884.         cSelectedTriangles = m_pmcSelectedMesh->ptmDrawMesh->GetNumFaces();
  885.         cSelectedVertices = m_pmcSelectedMesh->ptmDrawMesh->GetNumVertices();
  886.     }
  887.     else
  888.     {
  889.         cSelectedTriangles = 0;
  890.         cSelectedVertices = 0;
  891.     }
  892.  
  893.     UpdateStatusBar(cTriangles, cSelectedTriangles, cSelectedVertices);
  894.     return S_OK;
  895. }
  896.  
  897. #define FPS_FILTER 0.20
  898. #define FPS_UPDATE 10
  899.  
  900. HRESULT
  901. TrivialData::UpdateFrameRate(float fSecsPerFrame)
  902. {
  903.     float fFramesPerSecNew;
  904.     DWORD dwLastUpdateTime;
  905.     DWORD dwCurTime;
  906.  
  907.     m_fTime += fSecsPerFrame;
  908.  
  909.     // first calculate the current fps
  910.     fFramesPerSecNew = 1.0f / fSecsPerFrame;
  911.     if (m_fFramesPerSecCur == 0.0f)
  912.         m_fFramesPerSecCur = fFramesPerSecNew;
  913.     else
  914.         m_fFramesPerSecCur = (float)(fFramesPerSecNew * (1.0 - FPS_FILTER) + m_fFramesPerSecCur * FPS_FILTER);
  915.  
  916.     // now see if we should update the counter displayed
  917.     dwLastUpdateTime = (DWORD) (m_fLastUpdateTime * 2);
  918.     dwCurTime = (DWORD) (m_fTime * 2);
  919.  
  920.     if (dwCurTime > dwLastUpdateTime)
  921.     {
  922.         m_fLastUpdateTime = m_fTime;
  923.  
  924.         m_fFramesPerSec = m_fFramesPerSecCur;
  925.     }
  926.  
  927.     return S_OK;
  928. }
  929.  
  930. HRESULT
  931. TrivialData::UpdateStatusBar(DWORD cTotalTriangles, DWORD cTriangles, DWORD cVertices)
  932. {
  933.     char szBuf[256];
  934.  
  935.     sprintf(szBuf, "%d.%01d fps",
  936.                         (int)( m_fFramesPerSec * 10 ) / 10,
  937.                         (int)( m_fFramesPerSec * 10 ) % 10);
  938.     SendMessage(m_hwndStatus, SB_SETTEXT , (WPARAM) 2, (LPARAM) szBuf); 
  939.  
  940.     sprintf(szBuf, "%ld tps",
  941.                 (DWORD)(m_fFramesPerSec * cTotalTriangles)); //fTrisPerSecCur);
  942.     SendMessage(m_hwndStatus, SB_SETTEXT , (WPARAM) 3, (LPARAM) szBuf); 
  943.  
  944.     sprintf(szBuf, "%ld tri",
  945.                 cTriangles);
  946.     SendMessage(m_hwndStatus, SB_SETTEXT , (WPARAM) 4, (LPARAM) szBuf); 
  947.     
  948.     sprintf(szBuf, "%ld vert",
  949.                 cVertices);
  950.     SendMessage(m_hwndStatus, SB_SETTEXT , (WPARAM) 5, (LPARAM) szBuf); 
  951.  
  952.     return S_OK;
  953. }
  954.  
  955. HRESULT
  956. TrivialData::UpdateAnimation(SDrawElement *pde, float fSecsPerFrame)
  957. {
  958.     SFrame *pframeCur;
  959.  
  960.     //pde->fCurTime += fSecsPerFrame * 4800;
  961.     pde->fCurTime += fSecsPerFrame;// * m_fTicksPerSecond;
  962.     if (pde->fCurTime > 1.0e15f)
  963.     {
  964.         pde->fCurTime = 0;
  965.  
  966.         if (pde->m_pAnimMixer != NULL)
  967.             pde->m_pAnimMixer->ResetTime();
  968.     }
  969.  
  970.     if (pde->m_pAnimMixer != NULL)
  971.         pde->m_pAnimMixer->AdvanceTime(pde->fCurTime - pde->m_pAnimMixer->GetTime(), NULL);
  972.  
  973.     return S_OK;
  974. }
  975.  
  976. HRESULT
  977. TrivialData::OnUpdate(float fSecsPerFrame)
  978. {
  979.     SDrawElement *pdeCur;
  980.  
  981.     UpdateFrameRate(fSecsPerFrame);
  982.  
  983.     if (m_bAnimPaused)
  984.         return S_OK;
  985.  
  986.         pdeCur = m_pdeHead;
  987.         while (pdeCur != NULL)
  988.         {
  989.             UpdateAnimation(pdeCur, fSecsPerFrame);
  990.  
  991.             pdeCur = pdeCur->pdeNext;
  992.         }
  993.  
  994.     return S_OK;
  995. }
  996.